using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Web.UI.Design;
using PHSRAG.Insight21.ClinicalTrials;

using reportDownloadVisits = PHSRAG.Insight21.InsightWebControls.InsightDownloadBar;
using reportDownloadProcedures = PHSRAG.Insight21.InsightWebControls.InsightDownloadBar;
using Constants = PHSRAG.Insight21.InsightUtilities.Constants;

namespace PHSRAG.Insight21.InsightWebControls.ClinicalTrials
{
    /// <summary>
    /// The Budget Milestone Visits Control is used as a container for all BudgetTask and 
    /// Procedure controls.  It also contains buttons for action on the contained controls
    /// </summary>
    [ToolboxData("<{0}:BudgetMilestoneVisitsControl runat=server></{0}:BudgetMilestoneVisitsControl>"), Designer(typeof(BudgetMilestoneVisitsControlDesigner))]
    public class BudgetMilestoneVisitsControl : System.Web.UI.Control, INamingContainer
    {
        #region Instance Variables
        private Budget budget;
        private ArrayList budgetTaskControls = new ArrayList();
        private ArrayList budgetProcedureControls = new ArrayList();
        private Table tasksTable;
        private Table proceduresTable;
        private TableRow trVisits;
        private TableRow trTasksHeader;
        private TableRow trTasksTitle;
        private TableRow trTaskTotals;
        private TableRow trProceduresHeader;
        private TableRow trProceduresTitle;
        private TableRow trProceduresTotal;
        private Button addDefinedTask;
        private Button addOtherTask;
        private Button addProcedure;
        private Button saveMilestoneVisits;
        private Button deleteTasks;
        private Button deleteProcedures;
        private Button deleteVisit;
        private Button recalculateTasks;
        private Button recalculateProcedures;
        private ArrayList budgetVisitTextboxes = new ArrayList();
        private ArrayList deleteVisitList = new ArrayList();
        private ValidationSummary validationSummary;
        private CheckBox deleteVisitCheckbox;
        #endregion

        #region Constants
        private const int taskColumnsBeforeVisits = 7;
        private const int procedureColumnsBeforeVisits = 8;
        private const int blankTasksTotalRowColspan = 5;
        private const int tasksTableStaticWidth = 880;
        private const int proceduresTableStaticWidth = 880;
        private const int heightOfVisitsScreen = 200;
        private const int heightOfProceduresScreen = 110;
        private const int amtToAddPerTask = 25;
        private const int amtToAddPerProcedure = 35;
        #endregion

        private const string DownloadToExcel = "DownloadToExcel";
        private const string DownloadToPdf = "DownloadToPdf";

        private const string ProceduresDownloadToExcel = "ProceduresDownloadToExcel";
        private const string ProceduresDownloadToPdf = "ProceduresDownloadToPdf";

        private const string FailedActionCommand = "FailedAction";

        reportDownloadVisits rd;
        reportDownloadProcedures rdProcedures;

        public string SaveButtonClientId
        {
            get { EnsureChildControls(); return saveMilestoneVisits.ClientID; }
        }

        public string DeleteProceduresButtonClientId
        {
            get { EnsureChildControls(); return deleteProcedures.ClientID; }
        }

        public string DeleteTasksButtonClientId
        {
            get { EnsureChildControls(); return deleteTasks.ClientID; }
        }

        public string DeleteVisitButtonClientId
        {
            get { EnsureChildControls(); return deleteVisit.ClientID; }
        }

        #region Overrides
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            EnsureChildControls();
        }

        /// <summary>
        /// Runs upon loading of the control
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
        }

        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);
            rdProcedures.Dispose();
            rd.Dispose();
        }

        /// <summary>
        /// Returns an indicator showing whether the visit needs to be deleted 
        /// </summary>
        /// <param name="index"></param>
        /// <returns>bool</returns>
        public bool GetDeleteVisit(int index)
        {
            return ((CheckBox)deleteVisitList[index]).Checked;
        }

        /// <summary>
        /// Called by EnsureChildControls to add all child controls to the control tree.
        /// </summary>
        protected override void CreateChildControls()
        {
            budget = (Budget)((Policy.ICachePolicy)Page.Session[Policy.Names.CachePolicyKey]).GetCachedObject(Budget.CacheKey);
            CreateControls();
            GenerateControlTree();
        }

        /// <summary>
        /// Set the totals of the procedures and tasks in the respective tables
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            // Display the running totals of task costs
            int visits = budget.SubjectVisits;
            decimal totalHours = 0;
            decimal[] totalCost = new decimal[visits];
            decimal totalTotal = 0;
            foreach (BudgetTaskControl btc in budgetTaskControls)
            {
                // Hours may be blank on a new task control, this could happen if they 
                // refresh the page before saving the control
                if (!String.IsNullOrEmpty(btc.Hours))
                {
                    totalHours += decimal.Parse(btc.Hours);
                    for (int i = 0; i < visits; ++i)
                    {
                        totalCost[i] += btc.GetTaskCost(i);
                    }
                }
            }
            TableRow trTotals = (TableRow)FindControl("trTaskTotals");
            trTotals.Cells[1].Text = totalHours.ToString();
            for (int i = 0; i < visits; ++i)
            {
                trTotals.Cells[i + 3].Text = totalCost[i].ToString("c");
                totalTotal += totalCost[i];
            }
            trTotals.Cells[trTotals.Cells.Count - 1].Text = totalTotal.ToString("c");

            // Display the running totals of procedure costs
            totalCost = new decimal[visits];
            totalTotal = 0;
            foreach (BudgetProcedureControl bpc in budgetProcedureControls)
            {
                for (int i = 0; i < visits; ++i)
                {
                    totalCost[i] += bpc.GetProcedureCost(i);
                }
            }
            trTotals = (TableRow)FindControl("trProceduresTotal");
            for (int i = 0; i < visits; ++i)
            {
                trTotals.Cells[i + 1].Text = totalCost[i].ToString("c");
                totalTotal += totalCost[i];
            }
            trTotals.Cells[trTotals.Cells.Count - 1].Text = totalTotal.ToString("c");

        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Creates the actual controls, applying styles, setting values and binding validation.
        /// </summary>
        private void CreateControls()
        {
            tasksTable = new Table();
            proceduresTable = new Table();
            TableCell tdVisit = new TableCell();
            validationSummary = new ValidationSummary();
            validationSummary.HeaderText = "The following errors have occurred.";
            validationSummary.ShowSummary = true;

            // Create the Budget Vist, Task and Procedure controls
            BudgetVisits budgetVisits = budget.BudgetVisits;
            int visitsCount = budgetVisits.Count;

            #region Setup Tasks table controls
            #region Header Row
            trTasksHeader = new TableRow();
            TableCell tasksHeaderCell = new TableCell();
            tasksHeaderCell.ColumnSpan = taskColumnsBeforeVisits + visitsCount + 1;
            tasksHeaderCell.CssClass = "NoPad";
            Table tableTasksHeader = new Table();
            tableTasksHeader.CssClass = "ClinicalTrialsVisits";
            tableTasksHeader.CellPadding = 0;
            tableTasksHeader.CellSpacing = 0;

            TableRow tasksHeaderRow = new TableRow();
            tasksHeaderRow.Style.Value = "color:white; font-weight:bold; background-color:#5a76a0; height:5px";

            TableCell cell = new TableCell();
            cell.Text = "Tasks";
            cell.Width = 750;
            tasksHeaderRow.Cells.Add(cell);

            cell = new TableCell();
            cell.Width = 235;
            HtmlGenericControl rdSpan = new HtmlGenericControl("span");
            rdSpan.Attributes["class"] = "rdSpan";
            rd = new reportDownloadVisits();
            rd.SQLReportName = "CT_BudgetVisit";
            rd.StyleName = "ClinicalTrialDownloadBar";
            rdSpan.Controls.Add(rd);
            cell.Controls.Add(rdSpan);
            tasksHeaderRow.Cells.Add(cell);
            cell = new TableCell();
            cell.Text = "&nbsp;";
            tasksHeaderRow.Cells.Add(cell);

            tableTasksHeader.Rows.Add(tasksHeaderRow);
            tasksHeaderCell.Controls.Add(tableTasksHeader);
            trTasksHeader.Cells.Add(tasksHeaderCell);
            #endregion

            #region Title Row
            // Title row for the tasks table
            trTasksTitle = new TableRow();
            trTasksTitle.CssClass = "Title";

            TableCell tdDescription = new TableCell();
            tdDescription.CssClass = "TaskDescription";
            Label visitsHeader = new Label();
            visitsHeader.Text = "Task Description<br />(uncheck if Overhead should not be applied)";
            tdDescription.Controls.Add(visitsHeader);
            trTasksTitle.Cells.Add(tdDescription);

            TableCell tdHours = new TableCell();
            tdHours.CssClass = "Small";
            tdHours.Text = "Hours this<br />Task";
            trTasksTitle.Cells.Add(tdHours);

            TableCell tdPerson = new TableCell();
            tdPerson.CssClass = "Medium";
            tdPerson.Text = "Choose<br />Person";
            trTasksTitle.Cells.Add(tdPerson);

            TableCell tdOverRide = new TableCell();
            tdOverRide.CssClass = "Small";
            tdOverRide.Text = "Override task hours";
            trTasksTitle.Cells.Add(tdOverRide);

            TableCell tdCost = new TableCell();
            tdCost.CssClass = "Small";
            tdCost.Text = "Task<br />Charge";
            trTasksTitle.Cells.Add(tdCost);

            TableCell tdDelete = new TableCell();
            tdDelete.CssClass = "Delete";
            tdDelete.Text = "Delete";
            trTasksTitle.Cells.Add(tdDelete);

            TableCell tdCheckAll = new TableCell();
            tdCheckAll.CssClass = "Delete";
            tdCheckAll.Text = "Select All Visits <br /><br />Req|SOC";
            trTasksTitle.Cells.Add(tdCheckAll);

            for (int i = 1; i <= visitsCount; ++i)
            {
                tdVisit = new TableCell();
                tdVisit.CssClass = "Visits";
                tdVisit.Text = string.Format("Visit {0}{1}", i, "<br /><br />Req|SOC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Charge&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Delete&nbsp;Visit");
                trTasksTitle.Cells.Add(tdVisit);
            }
            TableCell tdTotal = new TableCell();
            tdTotal.CssClass = "Medium";
            tdTotal.Text = "Total per<br />Patient";
            trTasksTitle.Cells.Add(tdTotal);
            #endregion

            #region Visits Row
            // Row which holds the visit textboxes to set the visit labels
            trVisits = new TableRow();
            TableCell td = new TableCell();
            td.ColumnSpan = taskColumnsBeforeVisits;
            td.Text = String.Empty;
            td.Attributes["align"] = "right";
            trVisits.Cells.Add(td);

            for (int i = 0; i < visitsCount; ++i)
            {
                BudgetVisit budgetVisit = budgetVisits[i];
                tdVisit = new TableCell();
                TextBox visitLabel = new TextBox();
                visitLabel.ID = "textboxVisit" + i;
                visitLabel.CssClass = "DataInputExpanded";
                visitLabel.Text = budgetVisit.VisitDescription;
                budgetVisitTextboxes.Add(visitLabel);
                tdVisit.Controls.Add(visitLabel);
                deleteVisitCheckbox = new CheckBox();
                deleteVisitList.Add(deleteVisitCheckbox);
                Label space = new Label();
                space.Text = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                tdVisit.Controls.Add(space);
                tdVisit.Controls.Add(deleteVisitCheckbox);
                trVisits.Cells.Add(tdVisit);
            }
            td = new TableCell();
            td.Text = "&nbsp;";
            td.ColumnSpan = 2;
            trVisits.Cells.Add(td);
            #endregion

            #region Totals Row
            // Row which holds the totals for tasks
            trTaskTotals = new TableRow();
            trTaskTotals.ID = "trTaskTotals";
            TableCell tdLabel = new TableCell();
            tdLabel.Text = "<b>TOTAL (HOURS - PRICE)</b>";
            TableCell tdTotalHours = new TableCell();
            TableCell tdBlank = new TableCell();
            tdBlank.ColumnSpan = blankTasksTotalRowColspan;
            trTaskTotals.Cells.Add(tdLabel);
            trTaskTotals.Cells.Add(tdTotalHours);
            trTaskTotals.Cells.Add(tdBlank);
            for (int i = 1; i <= visitsCount; ++i)
            {
                tdVisit = new TableCell();
                tdVisit.CssClass = "Label";
                trTaskTotals.Cells.Add(tdVisit);
            }
            TableCell tdTotals = new TableCell();
            tdTotals.CssClass = "Label";
            trTaskTotals.Cells.Add(tdTotals);
            #endregion

            // Buttons beneath the tasks table			
            addDefinedTask = new Button();
            addDefinedTask.ID = "addDefinedTask";
            addDefinedTask.CssClass = "Button";
            addDefinedTask.Text = "Add Another Defined Task";
            addDefinedTask.Click += new EventHandler(OnAddDefinedTask);
            addOtherTask = new Button();
            addOtherTask.ID = "addOtherTask";
            addOtherTask.CssClass = "Button";
            addOtherTask.Text = "Add an \"Other\" Task";
            addOtherTask.Click += new EventHandler(OnAddOtherTask);
            deleteTasks = new Button();
            deleteTasks.ID = "deleteTasks";
            deleteTasks.CssClass = "Button";
            deleteTasks.Text = "Delete Tasks";
            //deleteTasks.Enabled = false;
            deleteTasks.Click += new EventHandler(OnDeleteTasks);
            deleteTasks.CausesValidation = false;
            deleteVisit = new Button();
            deleteVisit.ID = "deleteVisit";
            deleteVisit.CssClass = "Button";
            deleteVisit.Text = "Delete Visit";
            deleteVisit.Click += new EventHandler(OnDeleteVisit);
            recalculateTasks = new Button();
            recalculateTasks.ID = "recalculateTasks";
            recalculateTasks.CssClass = "Button";
            recalculateTasks.Text = "Recalculate";
            #endregion

            #region Setup Procedures table controls
            #region Header Row
            trProceduresHeader = new TableRow();
            TableCell proceduresHeaderCell = new TableCell();
            proceduresHeaderCell.CssClass = "NoPad";
            proceduresHeaderCell.ColumnSpan = procedureColumnsBeforeVisits + visitsCount + 1;
            Table tableProceduresHeader = new Table();
            tableProceduresHeader.CssClass = "ClinicalTrialsVisits";
            tableProceduresHeader.CellPadding = 0;
            tableProceduresHeader.CellSpacing = 0;

            TableRow proceduresHeaderRow = new TableRow();
            proceduresHeaderRow.Style.Value = "color:white; font-weight:bold; background-color:#5a76a0; height:5px";

            cell = new TableCell();
            cell.Text = "Procedures";
            cell.Width = 750;
            proceduresHeaderRow.Cells.Add(cell);

            cell = new TableCell();
            cell.Width = 235;
            rdSpan = new HtmlGenericControl("span");
            rdSpan.Attributes["class"] = "rdSpan";
            rdProcedures = new reportDownloadProcedures();
            rdProcedures.SQLReportName = "CT_ProcedureVisit";
            rdProcedures.StyleName = "ClinicalTrialDownloadBar";
            rdSpan.Controls.Add(rdProcedures);
            cell.Controls.Add(rdSpan);
            proceduresHeaderRow.Cells.Add(cell);
            cell = new TableCell();
            cell.Text = "&nbsp;";
            proceduresHeaderRow.Cells.Add(cell);
            tableProceduresHeader.Rows.Add(proceduresHeaderRow);
            proceduresHeaderCell.Controls.Add(tableProceduresHeader);
            trProceduresHeader.Cells.Add(proceduresHeaderCell);
            #endregion

            #region Title Row
            // Title row for the procedures table
            trProceduresTitle = new TableRow();
            trProceduresTitle.CssClass = "Title";

            TableCell tdProcedureDescription = new TableCell();
            tdProcedureDescription.CssClass = "ProcedureDescription";
            Label procedureHeader = new Label();
            procedureHeader.Text = "Procedure Description<br />(uncheck if Overhead should not be applied)";
            tdProcedureDescription.Controls.Add(procedureHeader);
            trProceduresTitle.Cells.Add(tdProcedureDescription);

            TableCell tdInpatient = new TableCell();
            tdInpatient.CssClass = "Small";
            tdInpatient.Text = "Inpatient<br />Procedure";
            trProceduresTitle.Cells.Add(tdInpatient);

            TableCell tdCharge = new TableCell();
            tdCharge.CssClass = "Small";
            tdCharge.Text = "Charge";
            trProceduresTitle.Cells.Add(tdCharge);

            TableCell tdResCharge = new TableCell();
            tdResCharge.CssClass = "Small";
            tdResCharge.Text = "Research<br />Charge";
            trProceduresTitle.Cells.Add(tdResCharge);

            TableCell tdProcCharge = new TableCell();
            tdProcCharge.CssClass = "Small";
            tdProcCharge.Text = "Procedure<br />Charge";
            trProceduresTitle.Cells.Add(tdProcCharge);

            TableCell tdFee = new TableCell();
            tdFee.CssClass = "Small";
            tdFee.Text = "Prof<br />Fee";
            trProceduresTitle.Cells.Add(tdFee);

            td = new TableCell();
            td.CssClass = "Delete";
            td.Text = "Delete";
            trProceduresTitle.Cells.Add(td);

            tdCheckAll = new TableCell();
            tdCheckAll.CssClass = "Delete";
            tdCheckAll.Text = "Select All Visits <br /><br />Req|SOC";
            trProceduresTitle.Cells.Add(tdCheckAll);

            for (int i = 1; i <= visitsCount; ++i)
            {
                tdVisit = new TableCell();
                tdVisit.CssClass = "Visits";
                tdVisit.Text = string.Format("Visit {0}{1}", i, "<br /><br />Req|SOC&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Charge");
                trProceduresTitle.Cells.Add(tdVisit);
            }

            tdTotal = new TableCell();
            tdTotal.CssClass = "Medium";
            tdTotal.Text = "Total per<br />Patient";
            trProceduresTitle.Cells.Add(tdTotal);
            #endregion

            #region Total Row
            // Row which holds the totals for the procedures
            trProceduresTotal = new TableRow();
            trProceduresTotal.ID = "trProceduresTotal";
            tdLabel = new TableCell();
            tdLabel.ColumnSpan = procedureColumnsBeforeVisits;
            tdLabel.Text = "<b>TOTAL (PRICE)</b>";
            trProceduresTotal.Cells.Add(tdLabel);
            for (int i = 1; i <= visitsCount; ++i)
            {
                tdVisit = new TableCell();
                tdVisit.CssClass = "Label";
                trProceduresTotal.Cells.Add(tdVisit);
            }

            tdTotals = new TableCell();
            tdTotals.CssClass = "Label";
            trProceduresTotal.Cells.Add(tdTotals);
            #endregion

            // buttons beneath the procedures table
            addProcedure = new Button();
            addProcedure.ID = "addProcedure";
            addProcedure.CssClass = "Button";
            addProcedure.Text = "Add Procedure";
            addProcedure.CssClass = "MilestoneVisitsControlSmallWidth";
            addProcedure.Click += new EventHandler(OnAddProcedure);

            deleteProcedures = new Button();
            deleteProcedures.ID = "deleteProcedures";
            deleteProcedures.CssClass = "Button";
            deleteProcedures.Text = "Delete Procedures";
            deleteProcedures.Click += new EventHandler(OnDeleteProcedures);
            deleteProcedures.CausesValidation = false;

            recalculateProcedures = new Button();
            recalculateProcedures.ID = "recalculateProcedures";
            recalculateProcedures.CssClass = "Button";
            recalculateProcedures.Text = "Recalculate";
            #endregion

            saveMilestoneVisits = new Button();
            saveMilestoneVisits.ID = "saveMilestoneVisits";
            saveMilestoneVisits.CssClass = "Button";
            saveMilestoneVisits.Text = "Save";
            saveMilestoneVisits.CssClass = "MilestoneVisitsControlSmallWidth";
            saveMilestoneVisits.Click += new EventHandler(OnSaveMilestoneVisits);

            BudgetTasks budgetTasks = budget.BudgetTasks;
            // For each budget Task object, create a control and add it to the arraylist
            int numberOfBudgetTasks = budgetTasks.Count;
            for (int i = 0; i < numberOfBudgetTasks; ++i)
            {
                BudgetTask budgetTask = budgetTasks[i];
                BudgetTaskControl newControl = new BudgetTaskControl(budgetTask, !String.IsNullOrEmpty(budgetTask.OtherTaskText) );
                newControl.ID = string.Format("budgetTask{0}", i);
                budgetTaskControls.Add(newControl);
            }

            // For each budget Procedure object, create a control and add it to the arraylist
            BudgetProcedures budgetProcedures = budget.BudgetProcedures;
            for (int i = 0; i < budgetProcedures.Count; ++i)
            {
                BudgetProcedureControl newControl = new BudgetProcedureControl(budgetProcedures[i], "budgetProcedure" + i);
                budgetProcedureControls.Add(newControl);
            }
        }

        /// <summary>
        /// Adds the controls to the control tree
        /// </summary>
        private void GenerateControlTree()
        {

            Controls.Add(validationSummary);

            #region Tasks
 
            Panel outerTasksDiv = new Panel();
            tasksTable.CssClass = "ClinicalTrialsVisits";
            if (budget.BudgetVisits.Count >= 5)
            {
                outerTasksDiv.CssClass = "clinicalTrialsDiv";
                outerTasksDiv.Style.Value = "height:" + GetTableHeight(0) + "px;";
            }
            tasksTable.Rows.Add(trTasksHeader);
            tasksTable.Rows.Add(trTasksTitle);
            tasksTable.Rows.Add(trVisits);

            foreach (BudgetTaskControl budgetTaskControl in budgetTaskControls)
            {
                tasksTable.Controls.Add(budgetTaskControl);
            }

            tasksTable.Rows.Add(trTaskTotals);

            outerTasksDiv.Controls.Add(tasksTable);
            Controls.Add(outerTasksDiv);

            #region Procedure Buttons
            Table tasksButtonsTable = new Table();
            TableRow emptyRow = new TableRow();
            TableCell emptyCell = new TableCell();
            emptyCell.Text = "&nbsp;";
            emptyRow.Cells.Add(emptyCell);
            tasksButtonsTable.Rows.Add(emptyRow);
            
            TableRow buttonsRow = new TableRow();
            TableCell buttonsCell = new TableCell();
            buttonsCell.Controls.Add(addDefinedTask);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(addOtherTask);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(deleteTasks);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(deleteVisit);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(recalculateTasks);
            buttonsRow.Cells.Add(buttonsCell);
            tasksButtonsTable.Rows.Add(buttonsRow);
            Controls.Add(tasksButtonsTable);
            #endregion
            #endregion

            Controls.Add(new HtmlGenericControl("br"));

            #region Procedures
            Panel outerProceduresDiv = new Panel();
            proceduresTable.CssClass = "ClinicalTrialsVisits";
            if ((budget.BudgetVisits.Count >= 5) && (budget.BudgetProcedures.Count != 0))
            {
                outerProceduresDiv.CssClass = "clinicalTrialsDiv";
                outerProceduresDiv.Style.Value = "height:" + GetTableHeight(1) + "px;";
            }
            else if ((budget.BudgetProcedures.Count == 0) || budget.BudgetVisits.Count < 5)
            {
                outerProceduresDiv.Style.Value = "height:200px;overflow:auto";
            }
            proceduresTable.Rows.Add(trProceduresHeader);
            proceduresTable.Rows.Add(trProceduresTitle);
            foreach (BudgetProcedureControl budgetProcedureControl in budgetProcedureControls)
            {
                proceduresTable.Controls.Add(budgetProcedureControl);
            }
            proceduresTable.Rows.Add(trProceduresTotal);

            outerProceduresDiv.Controls.Add(proceduresTable);
            Controls.Add(outerProceduresDiv);

            #region Procedure Buttons
            Table proceduresButtonsTable = new Table();
            proceduresButtonsTable.Rows.Add(emptyRow);

            buttonsRow = new TableRow();
            buttonsCell = new TableCell();

            buttonsCell.Controls.Add(addProcedure);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(deleteProcedures);
            buttonsCell.Controls.Add(new LiteralControl("&nbsp;"));
            buttonsCell.Controls.Add(recalculateProcedures);
            buttonsRow.Cells.Add(buttonsCell);
            proceduresButtonsTable.Rows.Add(buttonsRow);
            proceduresButtonsTable.Rows.Add(emptyRow);

            buttonsRow = new TableRow();
            buttonsCell = new TableCell();

            buttonsCell.Controls.Add(saveMilestoneVisits);
            buttonsRow.Cells.Add(buttonsCell);
            proceduresButtonsTable.Rows.Add(buttonsRow);
            Controls.Add(proceduresButtonsTable);
            #endregion
            #endregion
        }

        private int GetTableHeight(int type)
        {
            if (type == 0)
            {
                if (budgetTaskControls.Count == 1)
                {
                    return heightOfVisitsScreen;
                }
                else
                {
                    return (heightOfVisitsScreen + (budgetTaskControls.Count * amtToAddPerTask));
                }
            }
            else
            {
                if (budgetProcedureControls.Count == 1)
                {
                    return heightOfProceduresScreen;
                }
                else
                {
                    return (heightOfProceduresScreen + (budgetProcedureControls.Count * amtToAddPerProcedure));
                }
            }

        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Event handler for adding a new defined task
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddDefinedTask(object sender, EventArgs e)
        {
            BudgetTasks budgetTasks = budget.BudgetTasks;
            BudgetTask newBudgetTask = budgetTasks.CreateNewBudgetTask();
            BudgetTaskControl newControl = new BudgetTaskControl(newBudgetTask, false);
            newControl.ID = string.Format("budgetTask{0}", ((budgetTasks.Count - 1) as object));
            tasksTable.Controls.AddAt(tasksTable.Controls.IndexOf(trTaskTotals), newControl);
        }

        /// <summary>
        /// Event handler for adding a new "other" task
        /// </summary>		
        private void OnAddOtherTask(object sender, EventArgs e)
        {
            BudgetTasks budgetTasks = budget.BudgetTasks;
            BudgetTask newBudgetTask = budgetTasks.CreateNewBudgetTask();
            newBudgetTask.OtherTaskText = "Enter other task description.";
            BudgetTaskControl newControl = new BudgetTaskControl(newBudgetTask, true);
            newControl.ID = string.Format("budgetTask{0}", ((budgetTasks.Count - 1) as object));
            tasksTable.Controls.AddAt(tasksTable.Controls.IndexOf(trTaskTotals), newControl);
        }

        /// <summary>
        /// Event handler for adding a new procedure
        /// </summary>		
        private void OnAddProcedure(object sender, EventArgs e)
        {
            BudgetProcedures budgetProcedures = budget.BudgetProcedures;
            BudgetProcedure newBudgetProcedure = budgetProcedures.CreateNewBudgetProcedure();
            BudgetProcedureControl newControl = new BudgetProcedureControl(newBudgetProcedure, "budgetProcedure" + ((budgetProcedures.Count - 1) as object).ToString());
            newControl.ID = string.Format("budgetProcedure{0}", ((budgetProcedures.Count - 1) as object));
            proceduresTable.Controls.AddAt(proceduresTable.Controls.IndexOf(trProceduresTotal), newControl);
        }

        /// <summary>
        /// Saves all items ( visits, tasks and procedures )
        /// </summary>		
        private void OnSaveMilestoneVisits(object sender, EventArgs e)
        {
            // Set the description values on the BudgetVisit objects
            BudgetVisits budgetVisits = budget.BudgetVisits;
            for (int i = 0; i < budgetVisits.Count; ++i)
            {
                budgetVisits[i].VisitDescription = ((TextBox)budgetVisitTextboxes[i]).Text;
            }
            budgetVisits.Save(Utility.DataAccess.GetConnectionString());

            // Set the values on the Budget Task objects, including its budget milestone visits
            BudgetTasks budgetTasks = budget.BudgetTasks;
            for (int i = 0; i < budgetTasks.Count; ++i)
            {
                BudgetTask budgetTask = budgetTasks[i];
                BudgetTaskControl budgetTaskControl = (BudgetTaskControl)budgetTaskControls[i];
                budgetTask.ApplyOverhead = budgetTaskControl.ApplyOverhead;
                budgetTask.BudgetStaffId = Int32.Parse(budgetTaskControl.StaffId);
                budgetTask.BudgetTaskCode = budgetTaskControl.TaskCode;
                budgetTask.Hours = budgetTaskControl.Hours;
                budgetTask.TaskCost = budgetTaskControl.TaskCost;
                budgetTask.OtherTaskText = budgetTaskControl.OtherTaskText;
                budgetTask.OverRideRate = budgetTaskControl.OverRide;

                BudgetMilestoneVisits budgetMilestoneVisits = budgetTask.BudgetMilestoneVisits;
                for (int j = 0; j < budgetMilestoneVisits.Count; j++)
                {
                    BudgetMilestoneVisit budgetMilestoneVisit = budgetMilestoneVisits[j];
                    budgetMilestoneVisit.StandardOfCare = budgetTaskControl.GetStandardOfCare(j);
                    budgetMilestoneVisit.Required = budgetTaskControl.GetRequired(j);
                }
            }
            budget.BudgetTasks.Save(Utility.DataAccess.GetConnectionString());

            // Set the values on the Budget Procedure objects, including its budget milestone visits
            BudgetProcedures budgetProcedures = budget.BudgetProcedures;
            for (int i = 0; i < budgetProcedures.Count; ++i)
            {
                BudgetProcedure budgetProcedure = budgetProcedures[i];
                BudgetProcedureControl budgetProcedureControl = (BudgetProcedureControl)budgetProcedureControls[i];
                budgetProcedure.ApplyOverhead = budgetProcedureControl.ApplyOverhead;
                budgetProcedure.Inpatient = budgetProcedureControl.Inpatient;
                budgetProcedure.ProcedureChargeCode = Int32.Parse(budgetProcedureControl.ProcedureChargeCode);
                budgetProcedure.ProfessionalFee = budgetProcedureControl.ProfFee;
                budgetProcedure.ProcedureCost = budgetProcedureControl.ProcedureCost;

                BudgetMilestoneVisits budgetMilestoneVisits = budgetProcedure.BudgetMilestoneVisits;
                for (int j = 0; j < budgetMilestoneVisits.Count; j++)
                {
                    BudgetMilestoneVisit budgetMilestoneVisit = budgetMilestoneVisits[j];
                    budgetMilestoneVisit.StandardOfCare = budgetProcedureControl.GetStandardOfCare(j);
                    budgetMilestoneVisit.Required = budgetProcedureControl.GetRequired(j);
                }
            }
            budget.BudgetProcedures.Save(Utility.DataAccess.GetConnectionString());
        }

        /// <summary>
        /// Event handler for deleting tasks
        /// </summary>		
        private void OnDeleteTasks(object sender, EventArgs e)
        {
            BudgetTasks budgetTasks = budget.BudgetTasks;
            bool budgetTasksMarkedForDeletion = false;

            // Recurse through the list from the last item to the first, this keeps the counts 
            // synchronized, so we don't skip any or try to get controls or objects which don't 
            // exist anymore
            if (budgetTasks.Count > 0)
            {
                int lastItemIndex = budgetTasks.Count - 1;
                for (int i = lastItemIndex; i >= 0; --i)
                {
                    BudgetTaskControl budgetTaskControl = (BudgetTaskControl)budgetTaskControls[i];
                    if (budgetTaskControl.Delete)
                    {
                        budgetTasksMarkedForDeletion = true;
                        BudgetTask budgetTask = budgetTasks[i];
                        budgetTasks.RemoveBudgetTask(budgetTask);
                        tasksTable.Controls.RemoveAt(tasksTable.Controls.IndexOf(budgetTaskControl));
                    }
                }
                if (budgetTasksMarkedForDeletion)
                    budgetTasks.Save(Utility.DataAccess.GetConnectionString());
            }
        }

        /// <summary>
        /// Event handler for deleting procedures
        /// </summary>		
        private void OnDeleteProcedures(object sender, EventArgs e)
        {
            BudgetProcedures budgetProcedures = budget.BudgetProcedures;

            bool budgetProceduresMarkedForDeletion = false;
            // Recurse through the list from the last item to the first, this keeps the counts 
            // synchronized, so we don't skip any or try to get controls or objects which don't 
            // exist anymore
            if (budgetProcedures.Count > 0)
            {
                int lastItemIndex = budgetProcedures.Count - 1;
                for (int i = lastItemIndex; i >= 0; --i)
                {
                    BudgetProcedureControl budgetProcedureControl = (BudgetProcedureControl)budgetProcedureControls[i];
                    if (budgetProcedureControl.Delete)
                    {
                        BudgetProcedure budgetProcedure = budgetProcedures[i];
                        budgetProceduresMarkedForDeletion = true;
                        if (budgetProcedure.Id != 0) budgetProcedures.RemoveBudgetProcedure(budgetProcedure);
                        else budgetProcedures.RemoveBudgetProcedure(budgetProcedure,  i );
                        proceduresTable.Controls.RemoveAt(proceduresTable.Controls.IndexOf(budgetProcedureControl));
                    }
                }
                if (budgetProceduresMarkedForDeletion)
                    budgetProcedures.Save(Utility.DataAccess.GetConnectionString());
            }
        }

        /// <summary>
        /// Event handler for deleting a individual visit, also make sure to remove the milestone visit and change
        /// the number of visits
        /// </summary>		
        private void OnDeleteVisit(object sender, EventArgs e)
        {
            BudgetVisits budgetVisits = budget.BudgetVisits;
            BudgetProcedures budgetProcedures = budget.BudgetProcedures;
            BudgetTasks budgetTasks = budget.BudgetTasks;

            for (int i = budgetVisits.Count - 1; i >= 0; --i)
            {
                if (GetDeleteVisit(i))
                {
                    for (int j = budgetTasks.Count - 1; j >= 0; --j)
                    {
                        budgetTasks[j].BudgetMilestoneVisits.RemoveBudgetMilestoneVisit(budgetTasks[j].BudgetMilestoneVisits[i]);
                    }
                    for (int k = budgetProcedures.Count - 1; k >= 0; --k)
                    {
                        budgetProcedures[k].BudgetMilestoneVisits.RemoveBudgetMilestoneVisit(budgetProcedures[k].BudgetMilestoneVisits[i]);
                    }

                    budgetVisits.RemoveBudgetVisit(budgetVisits[i]);

                    budget.SubjectVisits = budget.SubjectVisits - 1;
                }
            }
            budget.Save(Utility.DataAccess.GetConnectionString());
            Page.Server.Transfer("BudgetVisits.aspx");
        }
        #endregion

    }

    #region Class BudgetMilestoneVisitsControlDesigner
    /// <summary>
    /// Designer associated with the BudgetMilestoneVisitsControl only used when the view of the web page is 
    /// switched to the design view from HTML.
    /// </summary>	
    public class BudgetMilestoneVisitsControlDesigner : ControlDesigner
    {
        #region Overrides
        /// <summary>
        /// Since the BudgetMilestoneVisitsControl does not have any design-time visibility, the designer provides
        /// the type name of that control and the name of the instance.
        /// </summary>
        /// <returns>HTML representation of the BudgetMilestoneVisitsControl</returns>
        public override string GetDesignTimeHtml()
        {
            return CreatePlaceHolderDesignTimeHtml();
        }
        #endregion
    }
    #endregion
}
